/*
 *       Copyright (c) 2008-2009 All rights reserved
 *               Asemantics S.r.l
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by
 *        Asemantics S.r.l."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Asemantics S.r.l.
 *    the Semantic Web company, Rome, London, Leiden and its contributors.
 *
 * 5. Neither the name of the company nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */


package com.asemantics.poco.persistence;

import com.asemantics.poco.Account;
import com.asemantics.poco.Activity;
import com.asemantics.poco.Address;
import com.asemantics.poco.BodyType;
import com.asemantics.poco.CurrentLocation;
import com.asemantics.poco.DateTime;
import com.asemantics.poco.Drinker;
import com.asemantics.poco.Email;
import com.asemantics.poco.Entry;
import com.asemantics.poco.Gender;
import com.asemantics.poco.IM;
import com.asemantics.poco.MediaItem;
import com.asemantics.poco.MediaItemType;
import com.asemantics.poco.Name;
import com.asemantics.poco.OSUrl;
import com.asemantics.poco.Organization;
import com.asemantics.poco.PhoneNumber;
import com.asemantics.poco.Photo;
import com.asemantics.poco.Relationship;
import com.asemantics.poco.Smoker;
import com.asemantics.poco.Url;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.net.URL;

/**
 * Fake <i>PoCo</i> model factory.
 *
 * @author Michele Mostarda ( michele.mostarda@gmail.com )
 */
public class FakeModelFactory {

    private FakeModelFactory() {}

    /**
     * Creates a fake {@link com.asemantics.poco.Name}.
     * @param i index to differentiate created instances.
     * @return a fake instance of name.
     */
    public static Name createName(int i) {
        Name name = new Name();
        name.setFamilyName("Pallino" + i);
        name.setGivenName("Pinco" + i);
        name.setMiddleName("Jr");
        name.setHonorificPrefix("Mr");
        name.setHonorificSuffix("Suff");
        return name;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.Organization}.
     * @param i index to differentiate created instances.
     * @return a fake instance of organization.
     */
    public static Organization createOrganization(int i) {
        Organization organization = new Organization();
        organization.setName("pincorg"+ i);
        organization.setDepartment("Org Dept " + i);
        organization.setTitle("The Pinco Org " + i);
        organization.setType("organization" + i);
        Calendar org1StartDateCalendar = new GregorianCalendar(2008, GregorianCalendar.JANUARY, 1);
        DateTime org1StartDate = new DateTime( org1StartDateCalendar.getTime(), TimeZone.getTimeZone("GMT") );
        organization.setStartDate(org1StartDate.getDate());
        Calendar org1EndDateCalendar = new GregorianCalendar(2008, GregorianCalendar.JANUARY, 2);
        DateTime org1EndDate = new DateTime( org1EndDateCalendar.getTime(), TimeZone.getTimeZone("GMT") );
        organization.setEndDate(org1EndDate.getDate());
        organization.setLocation("Org Dept Location " + i);
        organization.setDescription("The Pinco Org desc " + i);
        return organization;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.PhoneNumber}.
     * @param i index to differentiate created instances.
     * @return a fake instance of phone number.
     */
    public static PhoneNumber createPhoneNumber(int i) {
        PhoneNumber phoneNumber = new PhoneNumber();
        phoneNumber.setValue("123456789-" + i);
        phoneNumber.setType("work" + i);
        phoneNumber.setPrimary(false);
        return phoneNumber;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.Photo}.
     * @param i index to differentiate created instances.
     * @return a fake instance of photo.
     */
    public static Photo createPhoto(int i) {
        Photo photo = new Photo();
        photo.setValue("http://photos.pinco.it/" + i);
        photo.setType("work" + i);
        photo.setPrimary(false);
        return photo;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.IM}.
     * @param i index to differentiate created instances.
     * @return a fake instance of IM.
     */
    public static IM createIM(int i) {
        IM im = new IM();
        im.setValue("pinkoo" + i);
        im.setType("fun" + i);
        im.setPrimary(true);
        return im;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.Email}.
     * @param i index to differentiate created instances.
     * @return a fake instance of email.
     */
    public static Email createEmail(int i) {
        Email email = new Email();
        email.setPrimary(true);
        email.setValue("pinco" + i + "@pallino.it");
        email.setType("work" + 1);
        return email;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.Account}.
     * @param i index to differentiate created instances.
     * @return a fake instance of name.
     */
    public static Account createAccount(int i) {
       Account account = new Account();
        account.setDomain( "pincodom_" + i );
        account.setUsername("pinco" + i);
        account.setUserid("pincox");
        return account;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.MediaItem}.
     * @param i index to differentiate created instances.
     * @return a fake instance of media item.
     */
    public static MediaItem createMediaItem(int i) {
        try {
        MediaItem mediaItem = new MediaItem();
        mediaItem.setUrl( new URL( "http://video.pincopallino.it/" + i ) );
        mediaItem.setMediaItemType(MediaItemType.video);
        mediaItem.setMimeType("video/avi");
        return mediaItem;
        } catch (Exception e) {
           throw new RuntimeException("Error while creating fake mediaItem.");
        }
    }

    /**
     * Creates a fake {@link com.asemantics.poco.Activity}.
     * @param i index to differentiate created instances.
     * @return a fake instance of activity.
     */
    public static Activity createActivity(int i) {
        try {
            Activity activity = new Activity();
            activity.setId( BasePersistorTestCase.createUniqueKey("activity_id_") );
            activity.setAppId("Appo" + i);
            activity.setBody("Body" + i);
            activity.setBodyId("BodyID" + i);
            activity.setExternalId("ExternalID" + i);
            activity.setPostedTime(1244848849 + i);
            activity.setPriority(i);
            activity.setStreamFaviconUrl( new URL("http://favicon.pincopal.it/" + i) );
            activity.setStreamSourceUrl( new URL("http://source.pincopal.it/" + i) );
            activity.setStreamTitle("The Stream " + i);
            activity.setStreamUrl( new URL("http://stream.pincopal.it/" + i) );
            activity.setTitle("The Title " + i);
            activity.setTitleId("TitleID" + i);
            activity.setUrl( new URL("http://url.pincopal.it/" + i) );
            activity.setUserId("my.userid.pincopal.it" + i);
            activity.addMediaItem( createMediaItem(i)  );
        return activity;
        } catch (Exception e) {
            throw new RuntimeException("Error while creating fake activity.");
        }
    }

    /**
     * Creates a fake {@link com.asemantics.poco.Address}.
     * @param i index to differentiate created instances.
     * @return a fake instance of address.
     */
    public static Address createAddress(int i) {
        Address address = new Address();
        address.setCountry("Pinconia" + i);
        address.setFormatted("P I N C O N I A " + i);
        address.setLocality("Pincopola" + i);
        address.setPostalCode("123" + i);
        address.setRegion("Pincania" + i);
        address.setStreetAddress("Via di Pinco Pallino " + i);
        address.setType("work" + i);
        return address;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.BodyType}.
     * @param i index to differentiate created instances.
     * @return a fake instance of body type.
     */
    public static BodyType createBodyType(int i) {
        BodyType bodyType = new BodyType();
        bodyType.setBuild("thin" + i);
        bodyType.setEyeColor("Blue" + i);
        bodyType.setHairColor("Blonde" + i);
        bodyType.setHeight(1.76 + i);
        bodyType.setWeight(76  + i);
        return bodyType;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.CurrentLocation}.
     * @param i index to differentiate created instances.
     * @return a fake instance of current location.
     */
    public static CurrentLocation createCurrentLocation(int i) {
        CurrentLocation currentLocation = new CurrentLocation();
        currentLocation.setCountry("pinconia"  + i);
        currentLocation.setExtendedAddress("main street " + i);
        currentLocation.setLatitude(i);
        currentLocation.setLocality("Svitonia");
        currentLocation.setLongitude(2 * i);
        currentLocation.setPoBox("my-po-box-" + i);
        currentLocation.setPostalCode("1245" + i);
        currentLocation.setRegion("Regionia" + i);
        currentLocation.setStreetAddress("Another address " + i);
        currentLocation.setType("work" + i);
        currentLocation.setUnstructuredAddress("unstructured street " + i);
        return currentLocation;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.OSUrl}.
     * @param i index to differentiate created instances.
     * @return a fake instance of OS Url.
     */
    public static OSUrl createOsUrl(int i) {
        OSUrl osUrl = new OSUrl();
        osUrl.setAddress( "http://path.to.something/" + i );
        osUrl.setLinkText("my favourite url " + i);
        osUrl.setType("music");
        return osUrl;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.Entry}.
     * @return a fake instance of entry.
     */
    public static Entry createCompleteEntry() {
        Entry entry = new Entry();
        entry.setId( BasePersistorTestCase.createUniqueKey("entry_id_") );
        entry.setDisplayName("Pinco Pallino");

        entry.setName( createName(1) );

        entry.setNickname("pincopal");

        Calendar publishedCalendar = new GregorianCalendar(2008, GregorianCalendar.JANUARY, 23, 4, 56, 22);
        DateTime published = new DateTime( publishedCalendar.getTime(), TimeZone.getTimeZone("GMT") );
        entry.setPublished( published );

        Calendar updatedCalendar = new GregorianCalendar(2008, GregorianCalendar.JANUARY, 25, 4, 56, 22);
        DateTime updated = new DateTime( updatedCalendar.getTime(), TimeZone.getTimeZone("GMT") );
        entry.setUpdated( updated );

        Calendar birthdayCalendar = new GregorianCalendar(1979, GregorianCalendar.SEPTEMBER, 23);
        entry.setBirthday( birthdayCalendar.getTime() );

        Calendar anniversaryCalendar = new GregorianCalendar(1979, GregorianCalendar.SEPTEMBER, 23);
        entry.setAnniversary( anniversaryCalendar.getTime() );

        entry.setGender(Gender.male);

        entry.setNote("Nothing to declare...");

        entry.setPreferredUsername("pincopal79");

        entry.setUtcOffset(TimeZone.getTimeZone("GMT+01"));

        entry.setConnected(true);

        entry.setAboutMe("Nothing to say...");

        entry.setBodyType( createBodyType(1) );

        entry.setCurrentLocation( createCurrentLocation(1) );

        entry.setDrinker(Drinker.regularly);

        entry.setEthnicity("caucasian");

        entry.setFashion("no fashion");

        entry.setHappiestWhen("things work");

        entry.setHumor("bitter");

        entry.setLivingArrangement("apartment");

        entry.setLookingFor("drugs");

        entry.setProfileSong( createOsUrl(1) );
        entry.setProfileSong( createOsUrl(2) );

        entry.setRelationshipStatus("single");

        entry.setReligion("pagan");

        entry.setRomance("what?");

        entry.setScaredOf("caxisms");

        entry.setSexualOrientation("heterosexual");

        entry.setSmoker(Smoker.no);

        entry.setStatus("working...");

        entry.addEmail( createEmail(1) );
        entry.addEmail( createEmail(2) );

        Url url1 = new Url();
        url1.setValue("http://pinco.pallino.it");
        url1.setType("work");
        url1.setPrimary(false);
        entry.addUrl(url1);

        Url url2 = new Url();
        url2.setValue("http://pincofoo.pallino.it");
        url2.setType("fun");
        url2.setPrimary(true);
        entry.addUrl(url2);

        entry.addPhoneNumber( createPhoneNumber(1) );
        entry.addPhoneNumber( createPhoneNumber(2) );

        entry.addIM( createIM(1) );
        entry.addIM( createIM(2) );

        entry.addPhoto(createPhoto(1));
        entry.addPhoto(createPhoto(2));

        entry.addTag("pinco");
        entry.addTag("foo");

        entry.addRelationship("pinca");
        entry.addRelationship("pallina");

        entry.addAddress( createAddress(1) );
        entry.addAddress( createAddress(2) );

        entry.addOrganization( createOrganization(1) );
        entry.addOrganization( createOrganization(2) );

        entry.addAccount( createAccount(1) );
        entry.addAccount( createAccount(2) );

        entry.addActivity( createActivity(1) );

        entry.addBook("The donkey whisperer");
        entry.addBook("Go crazy in 10 days");

        entry.addCar("BMW");
        entry.addCar("Alfa-Romeo");

        entry.addChild("Bimbo Mix");
        entry.addChild("Bimba Mix");

        entry.addFood("gnocchi");
        entry.addFood("lasagne");

        entry.addHero("Spider Duck");
        entry.addHero("Monkey Rat");

        entry.addInterest("End this test");
        entry.addInterest("Survive this test");

        entry.addJobInterest("Java");
        entry.addJobInterest("Bava");

        entry.addLanguageSpoken("Pinco");
        entry.addLanguageSpoken("Pallian");

        entry.addMovie("The horrorific death test");
        entry.addMovie("The horrorific death test - resurrection");

        entry.addMusic("Zum pa ppa");
        entry.addMusic("Plin Plin");

        entry.addPet("donkey");
        entry.addPet("monkey");

        entry.addPoliticalView("democracy");
        entry.addPoliticalView("meritocracy");

        entry.addQuote("boh");
        entry.addQuote("bah");

        entry.addSport("pizza");
        entry.addSport("fichi");

        entry.addTurnOff("toff1");
        entry.addTurnOff("toff2");

        entry.addTurnOn("ton1");
        entry.addTurnOn("ton2");

        entry.addTvShow("Ending Test Today");
        entry.addTvShow("The Test is Ended");

        return entry;
    }

    /**
     * Creates a fake {@link com.asemantics.poco.Relationship}.
     * @return a fake instance of relationship.
     */
    public static Relationship createRelationship() {
        Relationship relationship = new Relationship();
        relationship.setKnows( createCompleteEntry() );
        relationship.setSubject( createCompleteEntry() );
        return relationship;
    }


}
